package com.hydra.cron.common.curator.selector;

import com.hydra.cron.common.utils.ObjectUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by lee on 15/12/13.
 */
public class LeaderEngine extends LeaderSelectorListenerAdapter implements Closeable {
    private LeaderSelector leaderSelector;
    private final AtomicInteger leaderCount = new AtomicInteger();
    private RunningListener listener;
    private AtomicBoolean isRun = new AtomicBoolean(false);

    public LeaderEngine(CuratorFramework client, String path) {
        leaderSelector = new LeaderSelector(client, path, this);
        leaderSelector.autoRequeue();
    }

    public void setListener(RunningListener listener) {
        this.listener = listener;
    }

    public LeaderSelector getLeaderSelector() {
        return leaderSelector;
    }

    public void start() throws IOException {
//        processStart();
        leaderSelector.start();
    }

    public void close() throws IOException {
        isRun.set(false);
        processStop();
        leaderSelector.close();
    }

    public void takeLeadership(CuratorFramework curatorFramework) throws Exception {
        isRun.set(true);
        processActiveEnter();

        System.out.println(" has been leader " + leaderCount.getAndIncrement() + " time(s) before.");
        try {
            while (isRun.get()) {
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            System.err.println(" was interrupted.");
            Thread.currentThread().interrupt();
        } finally {
            isRun.set(false);
            processActiveExit();
            System.out.println(" relinquishing leadership.\n");
        }
    }

    public boolean isLeader() {
        return isRun.get();
    }

    private void processStart() {
        if (ObjectUtil.isNotNull(listener)) {
            try {
                listener.processStart();
            } catch (Exception ignore) {

            }
        }
    }

    private void processStop() {
        if (ObjectUtil.isNotNull(listener)) {
            try {
                listener.processStop();
            } catch (Exception ignore) {

            }
        }
    }

    private void processActiveEnter() {
        if (ObjectUtil.isNotNull(listener)) {
            try {
                listener.processActiveEnter();
            } catch (Exception ignore) {

            }
        }
    }

    private void processActiveExit() {
        if (ObjectUtil.isNotNull(listener)) {
            try {
                listener.processActiveExit();
            } catch (Exception ignore) {

            }
        }
    }
}
